/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

void ReplaceChar( char *str , char src , char dst )
{
	char	*p = NULL ;
	
	for( p = str ; *p ; p++ )
	{
		if( *(p) == src )
			*(p) = dst ;
	}
	
	return;
}

#if ( defined _WIN32 )
char *strndup (const char *s, size_t n)
{
  char *result;
  size_t len = strlen (s);

  if (n < len)
    len = n;

  result = (char *) ZLMALLOC (len + 1);
  if (!result)
    return 0;

  result[len] = '\0';
  return (char *) memcpy (result, s, len);
}
#endif

char *StrdupEntireFile( char *pathfilename , int *p_file_size )
{
	struct stat	st ;
	char		*file_content = NULL ;
	int		file_size ;
	FILE		*fp = NULL ;
	
	int		nret = 0 ;
	
	nret = stat( pathfilename , & st ) ;
	if( nret == -1 )
	{
		return NULL;
	}
	file_size = (int)(st.st_size) ;
	
	file_content = (char*)ZLMALLOC( file_size+1 ) ;
	if( file_content == NULL )
	{
		return NULL;
	}
	memset( file_content , 0x00 , file_size+1 );
	
	fp = fopen( pathfilename , "rb" ) ;
	if( fp == NULL )
	{
		return NULL;
	}
	
	nret = fread( file_content , file_size , 1 , fp ) ;
	if( nret != 1 )
	{
		return NULL;
	}
	
	fclose( fp );
	
	if( p_file_size )
		(*p_file_size) = file_size ;
	return file_content;
}

int GetIpByDomainName( char *domain_name , size_t *ip_count , struct Ipv4DnsResolution **ip_array )
{
	struct addrinfo			hint ;
	struct addrinfo			*res = NULL ;
	struct addrinfo			*curr = NULL ;
	size_t				count ;
	struct Ipv4DnsResolution	*array = NULL , *p = NULL ;
	int				nret = 0 ;
	
	memset( & hint , 0x00 , sizeof(struct addrinfo) );
	hint.ai_family = AF_INET ;
	hint.ai_socktype = SOCK_STREAM ;
	nret = getaddrinfo( domain_name , NULL , & hint , & res ) ;
	if( nret )
		return nret;
	
	for( curr = res , count = 0 ; curr ; curr = curr->ai_next , count++ );
	array = (struct Ipv4DnsResolution *)ZLMALLOC( sizeof(struct Ipv4DnsResolution) * count ) ;
	if( array == NULL )
		return -1;
	
	for( curr = res , p = array ; curr ; curr = curr->ai_next , p++ )
	{
		p->ip_num = ((struct sockaddr_in *)(curr->ai_addr))->sin_addr.s_addr ;
		inet_ntop( AF_INET , & (p->ip_num) , p->ip_str , sizeof(p->ip_str) );
	}
	
	freeaddrinfo( res );
	
	if( ip_count )
		(*ip_count) = count ;
	if( ip_array )
		(*ip_array) = array ;
	else
		ZLFREE( array );
	return 0;
}

int IsMatchString(char *match_str, char *object_str, char match_much_characters, char match_one_character)
{
	if( match_str == NULL || object_str == NULL || match_much_characters == '\0' || match_one_character == '\0' )
		return -3;
	
	int el=strlen(match_str);
	int sl=strlen(object_str);
	char cs,ce;

	int is,ie;
	int last_xing_pos=-1;

	for(is=0,ie=0;is<sl && ie<el;){
		cs=object_str[is];
		ce=match_str[ie];

		if(cs!=ce){
			if(ce==match_much_characters){
				last_xing_pos=ie;
				ie++;
			}else if(ce==match_one_character){
				is++;
				/*
				if((unsigned)(cs)>0x7f && is+1>=sl)
					is++;
				*/
				ie++;
			}else if(last_xing_pos>=0){
				while(ie>last_xing_pos){
					ce=match_str[ie];
					if(ce==cs)
						break;
					ie--;
				}

				if(ie==last_xing_pos)
					is++;
			}else
				return -1;
		}else{
			is++;
			ie++;
		}
	}

	if(object_str[is]==0 && match_str[ie]==0)
		return 0;

	if(match_str[ie]==0)
		ie--;

	if(ie>=0){
		while(match_str[ie])
			if(match_str[ie++]!=match_much_characters)
				return -2;
	} 

	return 0;
}

int EscapeString( char *str )
{
	char	*p1 = NULL , *p2 = NULL ;
	int	len ;
	
	p1 = p2 = str ;
	len = 0 ;
	while( (*p2) )
	{
		if( (*p2) == '\\' )
		{
			p2++;
			if( (*p2) == 'a' )
			{
				(*p1) = '\a' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 'b' )
			{
				(*p1) = '\b' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 't' )
			{
				(*p1) = '\t' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 'n' )
			{
				(*p1) = '\n' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 'v' )
			{
				(*p1) = '\v' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 'f' )
			{
				(*p1) = '\f' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == 'r' )
			{
				(*p1) = '\r' ;
				p1++; len++;
				p2++;
			}
			else if( (*p2) == '\0' )
			{
				(*p1) = '\\' ;
				p1++; len++;
				return len;
			}
			else
			{
				(*p1) = (*p2) ;
				p1++; len++;
				p2++;
			}
		}
		else
		{
			(*p1) = (*p2) ;
			p1++; len++;
			p2++;
		}
	}
	
	(*p1) = '\0' ;
	return len;
}

int32_t TrimNumericLiteralUnderlineUnsafely( char *token , int32_t token_len , char *numeric_buffer )
{
	int32_t		numeric_buffer_len ;
	int32_t		i ;
	
	numeric_buffer_len = 0 ;
	for( i = 0 ; i < token_len ; i++ , token++ )
	{
		if( (*token) != '_' )
		{
			(*numeric_buffer++) = (*token) ;
			numeric_buffer_len++;
		}
	}
	(*numeric_buffer) = '\0' ;
	
	return numeric_buffer_len;
}

int GetFileType( char *pathfilename )
{
#if ( defined __linux__ ) || ( defined __unix ) || ( defined _AIX )
	struct stat	stat_buf;
	int		nret;
	
	nret = lstat( pathfilename , & stat_buf );
	if( nret == -1 )
		return -1;
	
	if( S_ISDIR(stat_buf.st_mode) )
		return FILE_TYPE_DIRECTORY;
	else if( S_ISREG(stat_buf.st_mode) )
		return FILE_TYPE_REGULAR;
	else if( S_ISCHR(stat_buf.st_mode) )
		return FILE_TYPE_CHARACTER;
	else if( S_ISBLK(stat_buf.st_mode) )
		return FILE_TYPE_BLOCK;
	else if( S_ISFIFO(stat_buf.st_mode) )
		return FILE_TYPE_FIFO;
	else if( S_ISSOCK(stat_buf.st_mode) )
		return FILE_TYPE_SOCKET;
	else if( S_ISLNK(stat_buf.st_mode) )
		return FILE_TYPE_LINK;
	else
		return FILE_TYPE_OTHER;
#elif defined(_WIN32)
	struct _stat	_stat_buf;
	int		nret;
	
	nret = _lstat( pathfilename , & _stat_buf) ;
	if( nret == -1 )
		return -1;
	
	if( _S_IFDIR & _stat_buf.st_mode )
		return FILE_TYPE_DIRECTORY;
	else if( _S_IFREG & _stat_buf.st_mode )
		return FILE_TYPE_REGULAR;
	else if( _S_IFCHR & _stat_buf.st_mode )
		return FILE_TYPE_CHARACTER;
	else if( _S_IFBLK & _stat_buf.st_mode )
		return FILE_TYPE_BLOCK;
	else if( _S_IFFIFO & _stat_buf.st_mode )
		return FILE_TYPE_FIFO;
	else if( _S_IFSOCK & _stat_buf.st_mode )
		return FILE_TYPE_SOCKET;
	else if( _S_IFLNK & _stat_buf.st_mode )
		return FILE_TYPE_LINK;
	else
		return FILE_TYPE_OTHER;
#else
	return -2;
#endif
}

void GetDirectoryWithFile( char *filename , char *pathname , size_t pathname_size )
{
	char	*p = NULL ;
	
	p = strrchr( filename , '/' ) ;
	if( p == NULL )
		return;
	
	snprintf( pathname , pathname_size , "%.*s" , (int)(p+1-filename),filename );
	
	return;
}

